package com.vision.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.vision.mapper.*;
import com.vision.pojo.entity.*;
import com.vision.pojo.vo.*;
import com.vision.service.VideoService;
import com.vision.utils.ThreadLocalUtil;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

@Service
public class VideoServiceImpl implements VideoService {

    @Autowired
    private VideoMapper videoMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private VideoTagMapper videoTagMapper;
    @Autowired
    private UserCollectMapper userCollectMapper;
    @Autowired
    private UserFollowMapper userFollowMapper;
    @Autowired
    private LikeVideoMapper likeVideoMapper;
    @Autowired
    private LikeCommentMapper likeCommentMapper;
    @Autowired
    private CommentMapper commentMapper;
    @Autowired
    private VideoHistoryMapper videoHistoryMapper;

    /**
     * 分页查询视频列表
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @param userId 用户id
     * @param state 视频状态
     * @return 视频列表
     */
    @Override
    public PageVO<Video> getVideoForPage(Integer pageNum, Integer pageSize, Integer userId, Integer state) {
        // 1. 新建 pageDTO 传输对象
        PageVO<Video> videoPageVO = new PageVO<>();

        // 2. 开启分页查询
        PageHelper.startPage(pageNum, pageSize);

        // 3. 查询视频列表
        List<Video> videoList = videoMapper.getVideoForPage(userId, state);

        // 4. 返回结果
        Page<Video> videos = (Page<Video>) videoList;
        videoPageVO.setTotal(videos.getTotal());
        videoPageVO.setItems(videos.getResult());

        return videoPageVO;
    }

    /**
     * 添加视频
     * @param video 视频
     */
    @Override
    public void addVideo(Video video) {
        // 1. 获取当前登录用户 ID
        Integer userId = getUserId();
        // 2. 设置视频的用户 ID
        video.setUserId(userId);
        // 3. 添加视频
        videoMapper.insertVideo(video);
    }

    /**
     * 获取正在审核中的视频
     * @return 用户 ID
     */
    @Override
    public Video getUnderReviewVideo() {
        // 1. 获取当前登录用户 ID
        Integer userId = getUserId();
        // 2. 查询当前用户视频中 state 为 2 的视频
        Video video = videoMapper.selectVideoByStateAndUserId(userId);
        // 3. 判空
        if (video == null) {
            throw new RuntimeException("当前用户没有上传视频");
        }
        return video;
    }

    /**
     * 获取所有正在审核中的视频
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @return 视频列表
     */
    @Override
    public PageVO<ReviewVideoVO> getAllUnderReviewVideo(@NotNull Integer pageNum ,@NotNull Integer pageSize) {
        // 1. 查询当前登录用户是否为管理员
        Integer userId = getUserId();
        User user = userMapper.selectUserById(userId);
        // 1.1 判空
        if (user == null) {
            String username = getUsername();
            stringRedisTemplate.delete(username); // 删除 token
            throw new RuntimeException("当前登录用户不存在");
        }
        // 2. 判断是否为管理员
        Integer role = user.getRole();
        if (role == 3) {
            String username = getUsername();
            stringRedisTemplate.delete(username); // 删除 token 使用户下线
            throw new RuntimeException("当前登录用户不是管理员");
        }
        // 3. 开启分页查询
        PageHelper.startPage(pageNum,pageSize);
        // 4. 查询
        Page<ReviewVideoVO> reviewVideoVOS =(Page<ReviewVideoVO>) videoMapper.selectAllUnderReviewVideo();

        // 5. 封装查询结果
        PageVO<ReviewVideoVO> pageVO = new PageVO<>();
        pageVO.setTotal(reviewVideoVOS.getTotal());
        pageVO.setItems(reviewVideoVOS.getResult());
        pageVO.setPageNum(pageNum);
        pageVO.setPageSize(pageSize);
        return pageVO;
    }

    /**
     * 视频通过审核
     * @param videoId 视频id
     */
    @Override
    public void updateReviewState(@NotNull Integer state,@NotNull Integer reviewProcess ,@NotNull Integer videoId) {
        videoMapper.updateReviewState(state,reviewProcess ,videoId);
    }

    /**
     * 删除视频
     * @param videoId 视频id
     */
    @Override
    public void deleteVideo(@NotNull Integer videoId) {
        // 删除所有与该视频相关的标签
        videoTagMapper.deleteTagByVideoId(videoId);
        // 删除收藏表中的该视频
        userCollectMapper.deleteCollectByVideoId(videoId);
        // 删除 视频点赞表 中所有与该视频相关的点赞
        likeVideoMapper.deleteByVideoId(videoId);
        // 删除 评论点赞表 所有与该视频相关评论的点赞
        List<Integer> commentList = commentMapper.selectCommentIdsByVideoId(videoId); // 获取所有与该视频相关的评论
        if (!commentList.isEmpty()) {
            likeCommentMapper.deleteLikeCommentByCommentIds(commentList); // 删除所有与该视频相关的评论的点赞
        }
        // 删除 评论表 中所有与该视频相关的评论
        commentMapper.deleteByVideoId(videoId);
        // 删除 历史播放表 中所有该视频的历史记录
        videoHistoryMapper.deleteByVideoId(videoId);
        // 删除视频
        videoMapper.deleteVideo(videoId);
    }

    /**
     * 更新视频
     * @param video 视频
     */
    @Override
    public void updateVideo(Video video) {
        videoMapper.updateVideo(video);
    }

    /**
     * 分页查询视频列表
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @return 视频列表
     */
    @Override
    public PageVO<VideoAndUserVO> getVideoForPageOrderByViewCount(Integer pageNum, Integer pageSize, String title) {
        // 1. 创建 pageVO
        PageVO<VideoAndUserVO> pageVO = new PageVO<>();
        // 2. 开启 pageVO
        PageHelper.startPage(pageNum,pageSize);
        // 3. 查询
        List<VideoAndUserVO> list = videoMapper.selectVideoForPageOrderByViewCount(title);
        // 4. 向下转型
        Page<VideoAndUserVO> videoList = (Page<VideoAndUserVO>)list;
        // 5. 封装结果
        pageVO.setTotal(videoList.getTotal());
        pageVO.setItems(videoList.getResult());
        pageVO.setPageNum(pageNum);
        pageVO.setPageSize(pageSize);
        // 6. 返回结果
        return pageVO;
    }

    /**
     * 分页查询视频列表
     * @param pageNum 页码
     * @param pageSize 每页数量
     * @param tagIds 标签id
     * @return 视频列表
     */
    @Override
    public PageVO<VideoAndUserVO> getVideoForPageByTagId(Integer pageNum, Integer pageSize, Integer[] tagIds) {
        // 1. 创建 pageVO
        PageVO<VideoAndUserVO> pageVO = new PageVO<>();
        // 2. 开启 pageVO
        PageHelper.startPage(pageNum,pageSize);
        // 3. 查询
        List<VideoAndUserVO> list = videoMapper.selectVideoForPageByTagId(tagIds);
        // 4. 向下转型
        Page<VideoAndUserVO> videoList = (Page<VideoAndUserVO>)list;
        // 5. 封装结果
        pageVO.setTotal(videoList.getTotal());
        pageVO.setItems(videoList.getResult());
        pageVO.setPageNum(pageNum);
        pageVO.setPageSize(pageSize);
        // 6. 返回结果
        return pageVO;
    }

    /**
     * 通过视频id获取视频
     * @param videoId 视频 id
     * @param userId 当前登录用户 ID
     * @return 视频
     */
    @Override
    public VideoVO getVideoById(Integer videoId,Integer userId) {
        // 1. 创建 videoVO
        VideoVO videoVO = new VideoVO();

        // 2. 获取视频
        Video video = videoMapper.selectVideoById(videoId);
        // 3. 判空
        if (video == null) {
            throw new RuntimeException("视频不存在");
        }
        // 4. 封装信息
        videoVO.setVideo(video);

        // 5. 获取用户信息
        User user = userMapper.selectUserById(video.getUserId());
        // 6. 判空
        if (user == null) {
            throw new RuntimeException("用户不存在");
        }
        // 7. 封装信息
        UserBriefVO userBriefVO = new UserBriefVO();
        userBriefVO.setId(user.getId());
        userBriefVO.setUsername(user.getUsername());
        userBriefVO.setNickname(user.getNickname());
        userBriefVO.setAvatar(user.getAvatar());
        userBriefVO.setUserDescription(user.getDescription());

        // 8. 获取是否关注该用户
        UserFollow userFollow =  userFollowMapper.selectByUserIdAndFollowId(user.getId(),userId);
        // 9. 判空
        if (userFollow != null) {
            userBriefVO.setIsSubscribed(1);
        } else {
            userBriefVO.setIsSubscribed(0);
        }
        videoVO.setUser(userBriefVO);

        // 10. 获取视频点赞数
        Integer likes = likeVideoMapper.selectCountByVideoId(videoId);
        // 11. 封装数据
        videoVO.setLikes(likes);

        // 12. 查询当前用户已点赞
        LikeVideo likeVideo = likeVideoMapper.selectByUserIdAndVideoId(userId,videoId);
        // 13. 判空且封装数据
        if (likeVideo != null) {
            videoVO.setIsLiked(1);
        } else {
            videoVO.setIsLiked(0);
        }

        // 14. 查询当前视频收藏量
        Integer collects = userCollectMapper.selectCountByVideoId(videoId);
        // 15. 封装数据
        videoVO.setCollects(collects);

        // 16. 查询当前用户是否收藏了该视频
        UserCollect userCollect = userCollectMapper.selectByUserIdAndVideoId(userId,videoId);
        // 17. 判空且封装数据
        if (userCollect != null) {
            videoVO.setIsCollected(1);
        } else {
            videoVO.setIsCollected(0);
        }

        // 18. 查询当前视频的所有标签
        List<Tag> tagList = videoTagMapper.selectTagsByVideoId(videoId);
        // 19. 封装数据
        videoVO.setTags(tagList);

        return videoVO;
    }

    /**
     * 增加视频播放量
     * @param videoId 视频 id
     */
    @Override
    public void addViewCount(Integer videoId) {
        videoMapper.updateVideoViewCountByVideoId(videoId);
    }

    /**
     * 获取当前安全线程中的用户 ID
     * @return 用户 ID
     */
    private Integer getUserId () {
        Map<String, Integer> userInfo = ThreadLocalUtil.get();
        return userInfo.get("id");
    }
    /**
     * 获取当前安全线程中的用户名
     * @return 用户名
     */
    private String getUsername () {
        Map<String, String> userInfo = ThreadLocalUtil.get();
        return userInfo.get("username");
    }
}
